/*
    File:       OSMutex.cpp

    Contains:   Platform - independent mutex header. The implementation of this object
                is platform - specific. Each platform must define an independent
                QTSSMutex.h & QTSSMutex.cpp file.
                
                This file is for Mac OS X Server only

    

*/

#include "OSMutex.h"
#include <stdlib.h>
#include <string.h>

#ifdef __Win32__
#define __PTHREADS_MUTEXES__  0
#else
#define __PTHREADS_MUTEXES__ 1
#endif


#if __PTHREADS_MUTEXES__
    static pthread_mutexattr_t  sMutexAttr;
    static void MutexAttrInit();
    
    #if __solaris__
            static pthread_once_t sMutexAttrInit = {PTHREAD_ONCE_INIT};
    #else
            static pthread_once_t sMutexAttrInit = PTHREAD_ONCE_INIT;
    #endif
    
#endif


#if __PTHREADS_MUTEXES__
void MutexAttrInit()
{
    //sMutexAttr = (pthread_mutexattr_t*)malloc(sizeof(pthread_mutexattr_t));
    ::memset(&sMutexAttr, 0, sizeof(pthread_mutexattr_t));
    pthread_mutexattr_init(&sMutexAttr);
}
#endif




OSMutex::OSMutex()
{
#ifdef __Win32__
	::InitializeCriticalSection(&fMutex);
#else
    (void)pthread_once(&sMutexAttrInit, MutexAttrInit);
    (void)pthread_mutex_init(&fMutex, &sMutexAttr);
#endif
	m_FirstLockThreadID = 0;
	
}

OSMutex::~OSMutex()
{
#ifdef __Win32__
    ::DeleteCriticalSection(&fMutex);
#else
    pthread_mutex_destroy(&fMutex);
#endif
}


void        OSMutex::Lock()
{
#ifdef __Win32__
    ::EnterCriticalSection(&fMutex);
    m_FirstLockThreadID = GetCurrentThread();
#else
    (void)pthread_mutex_lock(&fMutex);
    m_FirstLockThreadID = pthread_self();
#endif
}

void        OSMutex::Unlock()
{
       
#ifdef __Win32__
        ::LeaveCriticalSection(&fMutex);
#else
        pthread_mutex_unlock(&fMutex);
#endif

}

Bool      OSMutex::TryLock()
{

#ifdef __Win32__
    Bool theErr = (Bool)::TryEnterCriticalSection(&fMutex); // Return values of this function match our API
    if (!theErr)
        return theErr;
#else
    int theErr = pthread_mutex_trylock(&fMutex);
    if (theErr != 0)
    {
        Assert(theErr == EBUSY);
        return false;
    }
#endif

	return true;
}

